﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Xml.Serialization;
using System.Windows.Forms;

namespace FastAccess
{
    [Serializable]
    public enum FastMenuType
    {
        File,
        Folder,
        FolderAsMenuWithFiles,
        FolderAsMenuWithFolders,
        FolderAsMenuWithFilesAndFolders,
        RootMenu,
        Separator,
        Url
    };

    [Serializable]
    public class FastMenuItem : ICloneable
    {
        /* 
         * Ao adicionar um field novo, deve-se
         * adicioná-lo também aos metodos "SameValue" e "Copy". 
         */

        [XmlAttribute]
        public string ID { get; set; }
        [XmlAttribute]
        public string Caption { get; set; }
        [XmlAttribute]
        public string Path { get; set; }
        [XmlAttribute]
        public string Icon { get; set; }
        [XmlAttribute]
        public bool UseAssocietedIcon { get; set; }
        [XmlAttribute]
        public FastMenuType Type { get; set; }
        public List<FastMenuItem> Items { get; set; }

        public FastMenuItem() { }

        public FastMenuItem(string id)
        {
            this.ID = id;
            this.UseAssocietedIcon = true;
            this.Items = new List<FastMenuItem>();
        }

        public FastMenuItem(string id, string caption, FastMenuType type)
            : this(id)
        {
            this.Caption = caption;
            this.Type = type;
        }

        public FastMenuItem Find(string id)
        {
            FastMenuItem fastMenu = null;
            SearchAll(id, this, ref fastMenu);
            return fastMenu;
        }

        public FastMenuItem ValueOf(string id)
        {
            foreach (FastMenuItem fm in this.Items)
                if (fm.ID == id)
                    return fm;

            return null;
        }

        public void Remove(string ownerId, string id)
        {
            FastMenuItem fastMenu = null;
            SearchAll(id, this, ref fastMenu);
            FastMenuItem root = null;
            SearchAll(ownerId, this, ref root);
            if ((root != null) && (fastMenu != null))
                root.Items.Remove(fastMenu);
        }

        public void Swap(string menu1, string menu2)
        {
            int index1 = this.Items.IndexOf(Find(menu1));
            int index2 = this.Items.IndexOf(Find(menu2));

            if ((index1 != -1) && (index2 != -1))
            {
                FastMenuItem aux = new FastMenuItem();
                aux = this.Items[index1];
                this.Items[index1] = this.Items[index2];
                this.Items[index2] = aux;
            }
        }

        public void Execute()
        {
            try
            {
                switch (this.Type)
                {
                    case FastMenuType.File:
                        break;
                    case FastMenuType.Folder:
                        break;
                    case FastMenuType.FolderAsMenuWithFiles:
                        break;
                    case FastMenuType.FolderAsMenuWithFolders:
                        break;
                    case FastMenuType.FolderAsMenuWithFilesAndFolders:
                        break;
                    case FastMenuType.RootMenu:
                        break;
                    case FastMenuType.Separator:
                        break;
                    case FastMenuType.Url:
                        break;
                    default:
                        break;
                }




                //    (this.Type)
                //{
                //    //case FastMenuType.Application:
                //case FastMenuType.Document:
                //    if (File.Exists(this.FileUrl))
                //        Process.Start(this.FileUrl);
                //    else
                //        throw new ArgumentException(string.Format("The file \"{0}\" does not exist.", this.FileUrl));
                //    break;
                //case FastMenuType.Folder:
                //    if (Directory.Exists(this.FileUrl))
                //        Process.Start(this.FileUrl);
                //    else
                //        throw new ArgumentException(string.Format("The folder \"{0}\" does not exist.", this.FileUrl));
                //    break;
                //case FastMenuType.Url:
                //    Process.Start(this.FileUrl);
                //    break;
                //case FastMenuType.RootMenu:
                //case FastMenuType.Separator:
                //    default:
                //        break;
                //}
            }
            catch (Exception e)
            {
                System.Windows.Forms.MessageBox.Show(e.Message, "", System.Windows.Forms.MessageBoxButtons.OK,
                    System.Windows.Forms.MessageBoxIcon.Error);
            }
        }

        private void SearchAll(string name, FastMenuItem menu, ref FastMenuItem fastMenu)
        {
            if (menu.ID == name)
            {
                fastMenu = menu;
                return;
            }
            foreach (FastMenuItem fm in menu.Items)
                SearchAll(name, fm, ref fastMenu);
        }

        public object Clone()
        {
            return Clone(this);
        }

        private FastMenuItem Clone(FastMenuItem f)
        {
            FastMenuItem fmcopy = new FastMenuItem(f.ID, f.Caption, f.Type);
            fmcopy.Path = f.Path;
            fmcopy.UseAssocietedIcon = f.UseAssocietedIcon;

            for (int i = 0; i < f.Items.Count; i++)
                fmcopy.Items.Add(Clone(f.Items[i]));

            return fmcopy;
        }

        public bool SameValue(FastMenuItem obj)
        {
            if (obj == null)
                return false;

            return SameValue(this, obj);
        }

        private bool SameValue(FastMenuItem fm1, FastMenuItem fm2)
        {
            bool equal = ((fm1.ID == fm2.ID) &&
                (fm1.Caption == fm2.Caption) &&
                (fm1.Path == fm2.Path) &&
                (fm1.Type == fm2.Type) &&
                (fm1.UseAssocietedIcon == fm2.UseAssocietedIcon) &&
                (fm1.Items.Count == fm2.Items.Count));

            if (equal)
            {
                for (int i = 0; i < fm1.Items.Count; i++)
                    if ((!SameValue(fm1.Items[i], fm2.Items[i])))
                    {
                        equal = false;
                        break;
                    }
            }

            return equal;
        }

        #region Serialization

        public void Serialize()
        {
            FileStream fs = null;
            try
            {
                fs = new FileStream(Application.StartupPath + "\\FastMenus.XML", FileMode.Create);

                XmlSerializerNamespaces nameSpace = new XmlSerializerNamespaces();
                nameSpace.Add("", "");
                XmlSerializer s = new XmlSerializer(typeof(FastMenuItem));
                s.Serialize(fs, this, nameSpace);
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format(ex.Message, ex.StackTrace),
                    "XmlSerializer", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            if (fs != null)
                fs.Close();
        }

        public static FastMenuItem Deserialize()
        {
            FastMenuItem menu = null;
            try
            {
                if (File.Exists(Application.StartupPath + "\\FastMenuNodes.XML"))
                {
                    FileStream fs = new FileStream(Application.StartupPath + "\\FastMenuNodes.XML", FileMode.Open);
                    try
                    {
                        XmlSerializer s = new XmlSerializer(typeof(FastMenuItem));
                        menu = (FastMenuItem)s.Deserialize(fs);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(string.Format(ex.Message, ex.StackTrace),
                            "XmlSerializer", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    fs.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format(ex.Message, ex.StackTrace),
                    "XmlSerializer", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            if (menu == null)
                return new FastMenuItem("FastMenu", "FastMenu", FastMenuType.RootMenu);
            else
                return menu;
        }

        #endregion

    }
}
